# -*- Mode: python; coding: utf-8; tab-width: 8; indent-tabs-mode: t; -*-
#
# Copyright (C) 2007 - Łukasz Wiśniewski
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.

import clutter
import math

class NotifyData:
	def __init__ (self, album=None, artist=None, title=None, rating=0):
		self.album, self.artist =  album, artist
		self.title, self.rating =  title, rating

class Notify (clutter.Group):
	def __init__ (self, pixbuf):
		clutter.Group.__init__(self)
		self.attache = None
		self.hide_schedule = False
		
		# Background
		self.background = clutter.Texture()
		self.background.set_pixbuf(pixbuf)
		self.background.show()
		self.add(self.background)
		
		# Label
		self.label = clutter.Label()
		self.label.set_text(" ")
		self.label.set_line_wrap(False)
		#self.label.set_ellipsize(True)
		self.label.set_use_markup(True)
		(w, h) = self.background.get_size()
		self.label.set_size(w, h)
		self.label.show()
		self.add(self.label)
		
		# Notify timeline
		self.fly_timeline = clutter.Timeline(30, 60)
		self.fly_timeline.set_loop(False)
		self.fly_alpha = clutter.Alpha(self.fly_timeline, clutter.sine_inc_func)
		self.fly_behave_1 = clutter.BehaviourOpacity(self.fly_alpha, 0, 255)
		self.fly_behave_1.apply(self)
		self.fly_timeline.connect('completed', self.on_fly_completed)
		
		# Attache timeline
		self.attache_timeline = clutter.Timeline(60,60)
		self.attache_timeline.set_loop(False)
		self.attache_alpha = clutter.Alpha(self.attache_timeline, clutter.sine_inc_func)
		self.attache_behave_1 = clutter.BehaviourScale(self.attache_alpha, 1, 0.4)
		self.attache_behave_2 = clutter.BehaviourPath(self.attache_alpha, None) # None causes segfault but we append knots later
		self.attache_behave_3 = clutter.BehaviourOpacity(self.attache_alpha, 255, 175)
		self.attache_timeline.connect('new-frame', self.on_attache_new_frame)
		
	def on_fly_completed(self, tl):
		if (self.get_property('visible') and self.hide_schedule):
			clutter.Group.hide(self)
			self.hide_schedule = False
			
	def on_attache_new_frame (self, tl, frame_num):
		progress = float(frame_num)/tl.get_n_frames ()
		progress = (math.sin((progress-0.5)*math.pi)+1)/2	# 0->1 shift from linear to sinuoid
		if self.hide_schedule or not self.get_property('visible'):
			progress = 1 - progress
		(w, h) = self.attache.get_size()
		self.attache.rotate_z(330*progress, w/2, h/2)
		
	def show(self):
		self.hide_schedule = False
		if not self.attache==None:
			self.attache_timeline.stop()
			self.attache_alpha.set_func(clutter.sine_inc_func)
			self.attache_timeline.start()
		self.fly_timeline.pause()
		self.fly_alpha.set_func(clutter.sine_inc_func)
		
		self.fly_timeline.start()
		clutter.Group.show(self)
	
	def hide(self):
		self.hide_schedule = True
		if not self.attache==None:
			self.attache_timeline.stop()
			self.attache_alpha.set_func(clutter.sine_dec_func)
			self.attache_timeline.start()
		frame_num = self.fly_timeline.get_current_frame()
		self.fly_alpha.set_func(clutter.sine_dec_func)
		
		self.fly_timeline.start()
		
	def swap_visibility(self):
		if (self.get_property('visible') and self.hide_schedule == True):
			self.show()
		elif (self.get_property('visible')):
			self.hide()
		else:
			self.show()
		
	def attach_actor(self, actor):
		if self.attache == None:
			self.attache = actor
			# FIXME: find mroe clean solution to change layer order
			self.set_depth(-1)
			self.attache_behave_1.apply(self.attache)
			self.attache_behave_2.apply(self.attache)
			self.attache_behave_2.append_knots(self.attache.get_abs_position())
			(x, y) = self.get_abs_position()
			x += 7
			y += 7
			self.attache_behave_2.append_knots((x, y))
			self.attache_behave_3.apply(self.attache)
			# TODO: modifications on attache - need to be reveresed on detach
		else:
			raise Exception("actor already attached")
			
	def set_text(self, msg):
		if(len(msg)):
			# TODO: some formating here
			text = '<span color="white"><b>'+msg[2]+'</b>\nby <i>'+msg[0]+'</i></span>'
			self.label.set_text(text)
		
		PADING = 5
		(notify_w, notify_h) = self.get_size()
		(label_w, label_h) = self.label.get_size()
		self.label.set_position(PADING, notify_h-label_h-PADING)
